package com.cash.lemoloan.statisticlib.Utils;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.util.SparseArray;

import androidx.core.app.ActivityCompat;


import com.cash.lemoloan.statisticlib.StatisticApplication;
import com.cash.lemoloan.statisticlib.StatisticContant;

import java.io.File;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;




public class DevicesUtil {


    private static final int NETWORK_TYPE_UNAVAILABLE = -1;
    private static final int NETWORK_TYPE_WIFI = -101;

    private static final int NETWORK_CLASS_WIFI = -101;
    private static final int NETWORK_CLASS_UNAVAILABLE = -1;
    /**
     * Unknown network class.
     */
    private static final int NETWORK_CLASS_UNKNOWN = 0;
    /**
     * Class of broadly defined "2G" networks.
     */
    private static final int NETWORK_CLASS_2_G = 1;
    /**
     * Class of broadly defined "3G" networks.
     */
    private static final int NETWORK_CLASS_3_G = 2;
    /**
     * Class of broadly defined "4G" networks.
     */
    private static final int NETWORK_CLASS_4_G = 3;
    /**
     * Network type is unknown
     */
    public static final int NETWORK_TYPE_UNKNOWN = 0;
    /**
     * Current network is GPRS
     */
    public static final int NETWORK_TYPE_GPRS = 1;
    /**
     * Current network is EDGE
     */
    public static final int NETWORK_TYPE_EDGE = 2;
    /**
     * Current network is UMTS
     */
    public static final int NETWORK_TYPE_UMTS = 3;
    /**
     * Current network is CDMA: Either IS95A or IS95B
     */
    public static final int NETWORK_TYPE_CDMA = 4;
    /**
     * Current network is EVDO revision 0
     */
    public static final int NETWORK_TYPE_EVDO_0 = 5;
    /**
     * Current network is EVDO revision A
     */
    public static final int NETWORK_TYPE_EVDO_A = 6;
    /**
     * Current network is 1xRTT
     */
    public static final int NETWORK_TYPE_1xRTT = 7;
    /**
     * Current network is HSDPA
     */
    public static final int NETWORK_TYPE_HSDPA = 8;
    /**
     * Current network is HSUPA
     */
    public static final int NETWORK_TYPE_HSUPA = 9;
    /**
     * Current network is HSPA
     */
    public static final int NETWORK_TYPE_HSPA = 10;
    /**
     * Current network is iDen
     */
    public static final int NETWORK_TYPE_IDEN = 11;
    /**
     * Current network is EVDO revision B
     */
    public static final int NETWORK_TYPE_EVDO_B = 12;
    /**
     * Current network is LTE
     */
    public static final int NETWORK_TYPE_LTE = 13;
    /**
     * Current network is eHRPD
     */
    public static final int NETWORK_TYPE_EHRPD = 14;
    /**
     * Current network is HSPA+
     */
    public static final int NETWORK_TYPE_HSPAP = 15;


    /**
     * 获取手机型号
     */
    public static String getDeviceModel() {
        return Build.MODEL;
    }
    /**
     * 获取手机os系统
     */
    public static String getDeviceOsVersion() {
        return Build.VERSION.RELEASE;
    }
    /**
     * 品牌
     * @return String
     */
    public static String getBrand() {
        return Build.BRAND;
    }

    /**
     * 产品名
     * @return String
     */
    public static String getProduct() {
        return Build.PRODUCT;
    }

    /**
     * 制造商
     * @return String
     */
    public static String getManufacturer() {
        return Build.MANUFACTURER;
    }

    /**
     * 设备名
     * @return String
     */
    public static String getDevice() {
        return Build.DEVICE;
    }
    /**
     * 硬件
     * @return String
     */
    public static String getHardware() {
        return Build.HARDWARE;
    }
    /**
     * 源码控制版本号
     * @return String
     */
    public static String getBuildIncremental() {
        return Build.VERSION.INCREMENTAL;
    }

    /**
     * 主板
     * @return String
     */
    public static String getBoard() {
        return Build.BOARD;
    }

    /**
     * 主板引导程序
     * @return String
     */
    public static String getBootloader() {
        return Build.BOOTLOADER;
    }

    /**
     * 构建时间
     * @return String
     */
    public static long getBuildTime() {
        return Build.TIME;
    }
    /**
     * Radio版本
     * @return String
     */
    public static String getRadioVersion() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            return Build.getRadioVersion();
        }
        return "";
    }
    public static String getBluetoothName() {
        try {
            String name = BluetoothAdapter.getDefaultAdapter().getName();
            return TextUtils.isEmpty(name) ? "No bluetooth" : name;
        } catch (Exception e) {
            return "No bluetooth";
        }
    }
    /**
     * 获取SIM卡的iccid
     * @param context
     * @return
     */
    public static String getSIMICCID(Context context){
        if(null != context) {
            try{
                TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                if(tm != null){
                    return tm.getSimSerialNumber();
                }else{
                    return "";
                }
            }catch (Throwable tr){
                return "";
            }

        }
        return "";
    }
    /**
     * 判断手机是否Root
     * @return 是否Root
     */
    public static boolean isDeviceRooted() {
        String su = "su";
        String[] locations = {
                "/sbin/", "/system/bin/", "/system/xbin/", "/system/sd/xbin/", "/system/bin/failsafe/",
                "/data/local/xbin/", "/data/local/bin/", "/data/local/"
        };
        for (String location : locations) {
            if (new File(location + su).exists()) {
                return true;
            }
        }
        return false;
    }
    /**
     * 是否使用代理(WiFi状态下的,避免被抓包)
     */
    public static boolean isWifiProxy(Context context){
        try {
            final boolean is_ics_or_later = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
            String proxyAddress;
            int proxyPort;
            if (is_ics_or_later) {
                proxyAddress = System.getProperty("http.proxyHost");
                String portstr = System.getProperty("http.proxyPort");
                proxyPort = Integer.parseInt((portstr != null ? portstr : "-1"));
                System.out.println(proxyAddress + "~");
                System.out.println("port = " + proxyPort);
            } else {
                proxyAddress = android.net.Proxy.getHost(context);
                proxyPort = android.net.Proxy.getPort(context);
            }
            return (!TextUtils.isEmpty(proxyAddress)) && (proxyPort != -1);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return false;
    }
    /**
     * 是否正在使用VPN
     */
    public static boolean isVpnUsed() {
        try {
            Enumeration niList = NetworkInterface.getNetworkInterfaces();
            if(niList != null) {
                List<NetworkInterface> list = Collections.list(niList);
                for (NetworkInterface intf : list) {
                    if(!intf.isUp() || intf.getInterfaceAddresses().size() == 0) {
                        continue;
                    }
                    if ("tun0".equals(intf.getName()) || "ppp0".equals(intf.getName())){
                        return true; // The VPN is up
                    }
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return false;
    }
    public static int getWindowWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    public static int getWindowHeight(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;
    }
    /**
     * 系统启动时间戳
     */
    public static long getStartTime(){
        return System.currentTimeMillis() - SystemClock.elapsedRealtime();
    }



    /**
     * 获取网络类型
     *
     * @return
     */
    public static String getCurrentNetworkType() {
        int networkClass = getNetworkClassByType(getNetworkClass());
        String type = "UNKNOWN";
        switch (networkClass) {
            case NETWORK_CLASS_UNAVAILABLE:
                type = "无网络";
                break;
            case NETWORK_CLASS_WIFI:
                type = "WIFI";
                break;
            case NETWORK_CLASS_2_G:
                type = "2G";
                break;
            case NETWORK_CLASS_3_G:
                type = "3G";
                break;
            case NETWORK_CLASS_4_G:
                type = "4G";
                break;
            default:
                break;
        }
        return type;
    }

    public static int getNetworkClass() {
        int networkType = NETWORK_TYPE_UNKNOWN;
        try {
            final NetworkInfo network = ((ConnectivityManager) StatisticApplication
                    .getInstance()
                    .getSystemService(Context.CONNECTIVITY_SERVICE))
                    .getActiveNetworkInfo();
            if (network != null && network.isAvailable()
                    && network.isConnected()) {
                int type = network.getType();
                if (type == ConnectivityManager.TYPE_WIFI) {
                    networkType = NETWORK_TYPE_WIFI;
                } else if (type == ConnectivityManager.TYPE_MOBILE) {
                    TelephonyManager telephonyManager = (TelephonyManager) StatisticApplication
                            .getInstance().getSystemService(
                                    Context.TELEPHONY_SERVICE);
                    networkType = telephonyManager.getNetworkType();
                }
            } else {
                networkType = NETWORK_TYPE_UNAVAILABLE;
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return networkType;
    }

    private static int getNetworkClassByType(int networkType) {
        switch (networkType) {
            case NETWORK_TYPE_UNAVAILABLE:
                return NETWORK_CLASS_UNAVAILABLE;
            case NETWORK_TYPE_WIFI:
                return NETWORK_CLASS_WIFI;
            case NETWORK_TYPE_GPRS:
            case NETWORK_TYPE_EDGE:
            case NETWORK_TYPE_CDMA:
            case NETWORK_TYPE_1xRTT:
            case NETWORK_TYPE_IDEN:
                return NETWORK_CLASS_2_G;
            case NETWORK_TYPE_UMTS:
            case NETWORK_TYPE_EVDO_0:
            case NETWORK_TYPE_EVDO_A:
            case NETWORK_TYPE_HSDPA:
            case NETWORK_TYPE_HSUPA:
            case NETWORK_TYPE_HSPA:
            case NETWORK_TYPE_EVDO_B:
            case NETWORK_TYPE_EHRPD:
            case NETWORK_TYPE_HSPAP:
                return NETWORK_CLASS_3_G;
            case NETWORK_TYPE_LTE:
                return NETWORK_CLASS_4_G;
            default:
                return NETWORK_CLASS_UNKNOWN;
        }
    }




    /**
     * 初始化获取mac地址
     */
    public static String getMacAddress(){
        String macAddr = "";
        if(TextUtils.isEmpty(macAddr) || StatisticContant.NEW_CASHWIFI_CLOSED_UNABLE_ADDR.equals(macAddr) || StatisticContant.NEW_CASHWIFI_OPENED_UNABLE_MAC_ADDR.equals(macAddr)) {
            macAddr = getMacAddr2();
            if(TextUtils.isEmpty(macAddr) || StatisticContant.NEW_CASHWIFI_DEFAULT_MAC_ADDR.equals(macAddr)){
                macAddr = getMacAddr1();
            }
            if(TextUtils.isEmpty(macAddr) || StatisticContant.NEW_CASHWIFI_DEFAULT_MAC_ADDR.equals(macAddr)){
                WifiManager wifiManager = (WifiManager) StatisticApplication.getInstance().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                if(wifiManager.isWifiEnabled()){
                    macAddr = StatisticContant.NEW_CASHWIFI_OPENED_UNABLE_MAC_ADDR;
                }else{
                    macAddr = StatisticContant.NEW_CASHWIFI_CLOSED_UNABLE_ADDR;
                }
            }
            return macAddr;
        }else{
            return macAddr;
        }
    }
    /**
     * 获取当前设备的MAC地址
     */
    public static String getMacAddr2() {
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
                byte[] macBytes = nif.getHardwareAddress();
                if (macBytes == null) {
                    return "";
                }
                StringBuilder res1 = new StringBuilder();
                for (byte b : macBytes) {
                    res1.append(String.format("%02X:", b));
                }
                if (res1.length() > 0) {
                    res1.deleteCharAt(res1.length() - 1);
                }
                return res1.toString();
            }
        } catch (Exception ex) {
        }
        return  "";
    }
    public static String getMacAddr1(){
        Context context = StatisticApplication.getInstance();
        if (null == context) {
            return null;
        }
        String mac = null;
        try {
            WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo info = wm.getConnectionInfo();
            mac = info.getMacAddress();
        } catch (Exception e) {
        }
        return mac;
    }

    private static String sIMei = "",sIMsi = "";

    public static String getIMei() {
        checkIfContextInitialized();
        if (StatisticApplication.getInstance() == null) {
            return sIMei;
        }
        sIMei = getIMEIInner();
        if (TextUtils.isEmpty(sIMei)) {
            sIMei = "";
        }
        return sIMei;
    }
    public static String getIMEIInner() {
        String iMei = "";
        try {
            TelephonyManager mTelephonyMgr = (TelephonyManager) StatisticApplication.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
            if (ActivityCompat.checkSelfPermission(StatisticApplication.getInstance(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                iMei = "NO_PERMISSION";
                return iMei;
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                iMei = mTelephonyMgr.getImei();
            } else {
                iMei = mTelephonyMgr.getDeviceId();
            }
        } catch (Exception e) {
            Log.getStackTraceString(e);
        }
        return iMei;
    }

    public static String getIMsi() {
        checkIfContextInitialized();
        if (StatisticApplication.getInstance() == null) {
            return sIMsi;
        }
        sIMsi = getIMSIInner();
        if (TextUtils.isEmpty(sIMsi)) {
            sIMsi = "";
        }
        return sIMsi;
    }
    public static String getIMSIInner() {
        String iMsi = "";
        try {
            TelephonyManager mTelephonyMgr = (TelephonyManager) StatisticApplication.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
            if (ActivityCompat.checkSelfPermission(StatisticApplication.getInstance(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                iMsi = "NO_PERMISSION";
                return iMsi;
            }
            iMsi = mTelephonyMgr.getSubscriberId();
        } catch (Exception e) {
            Log.getStackTraceString(e);
        }
        return iMsi;
    }
    private static void checkIfContextInitialized() {
        if (StatisticApplication.getInstance() == null) {
            try {
                throw new Exception(
                        "context has not been initialized! You MUST call this only after initialize() is invoked.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    private static SparseArray<Integer> mChannelFrequency = new SparseArray<>();

    static {
        //2.4G
        mChannelFrequency.put(1, 2412);
        mChannelFrequency.put(2, 2417);
        mChannelFrequency.put(3, 2422);
        mChannelFrequency.put(4, 2427);
        mChannelFrequency.put(5, 2432);
        mChannelFrequency.put(6, 2437);
        mChannelFrequency.put(7, 2442);
        mChannelFrequency.put(8, 2447);
        mChannelFrequency.put(9, 2452);
        mChannelFrequency.put(10, 2457);
        mChannelFrequency.put(11, 2462);
        mChannelFrequency.put(12, 2467);
        mChannelFrequency.put(13, 2472);
        mChannelFrequency.put(14, 2484);

        //5G
        mChannelFrequency.put(36, 5180);
        mChannelFrequency.put(40, 5200);
        mChannelFrequency.put(44, 5220);
        mChannelFrequency.put(48, 5240);
        mChannelFrequency.put(52, 5260);
        mChannelFrequency.put(56, 5280);
        mChannelFrequency.put(60, 5300);
        mChannelFrequency.put(64, 5320);
        mChannelFrequency.put(100, 5500);
        mChannelFrequency.put(104, 5520);
        mChannelFrequency.put(108, 5540);
        mChannelFrequency.put(112, 5560);
        mChannelFrequency.put(116, 5580);
        mChannelFrequency.put(120, 5600);
        mChannelFrequency.put(124, 5620);
        mChannelFrequency.put(128, 5640);
        mChannelFrequency.put(132, 5660);
        mChannelFrequency.put(136, 5680);
        mChannelFrequency.put(140, 5700);
        mChannelFrequency.put(149, 5745);
        mChannelFrequency.put(153, 5765);
        mChannelFrequency.put(157, 5785);
        mChannelFrequency.put(161, 5805);
        mChannelFrequency.put(165, 5825);
    }

    /**
     * 2.4G and 5G
     */
    public static int getChannel(int frequency) {
        for (int i = 0; i < mChannelFrequency.size(); i++) {
            if (mChannelFrequency.valueAt(i) == frequency) {
                return mChannelFrequency.keyAt(i);
            }
        }
        return -1;
    }

    public static String getLocalIPV4Address(){
        String ipAddr = "an error occurred when obtaining ip address";
        try {
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
            while (en.hasMoreElements()) {
                NetworkInterface intf = en.nextElement();
                Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();
                while (enumIpAddr.hasMoreElements()) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        if (inetAddress instanceof Inet4Address){
                            String tempIpAddr = inetAddress.getHostAddress();
                            if(!TextUtils.isEmpty(tempIpAddr)){
                                return tempIpAddr;
                            }
                        }
                    }
                }
            }
        } catch (SocketException e) {
            return ipAddr;
        }
        return ipAddr;
    }

    /**
     * 获取路由器ip地址
     * @return
     */
    public static String getRouterIPAddress() {
        Context context = StatisticApplication.getInstance();

        WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (null != wifiManager){
            DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
            if ( null != dhcpInfo ){
                return Formatter.formatIpAddress(dhcpInfo.gateway);
            }
        }
        return null;
    }

    public static boolean isWifiAvailable() {
        return ConnectivityManager.TYPE_WIFI == getConnectedType();
    }
    private static int getConnectedType() {
        Context context = StatisticApplication.getInstance();
        if (context == null) {
            return -1;
        }

        ConnectivityManager connectivityManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return -1;
        }
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo != null
                && networkInfo.isAvailable()) {
            return networkInfo.getType();
        }
        return -1;
    }
}
